<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Faiss 向量搜索引擎 - 性能对比平台</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        :root {
            --primary: #4361ee;
            --secondary: #3f37c9;
            --success: #4cc9f0;
            --info: #4895ef;
            --warning: #f72585;
            --light: #f8f9fa;
            --dark: #212529;
            --gray: #6c757d;
        }
        
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: var(--dark);
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1400px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }
        
        header {
            background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
            color: white;
            padding: 30px 40px;
            text-align: center;
        }
        
        h1 {
            font-size: 2.8rem;
            margin-bottom: 10px;
            font-weight: 700;
        }
        
        .subtitle {
            font-size: 1.3rem;
            opacity: 0.9;
            font-weight: 300;
        }
        
        .content {
            display: grid;
            grid-template-columns: 300px 1fr;
            min-height: 800px;
        }
        
        .sidebar {
            background: var(--light);
            padding: 25px;
            border-right: 1px solid #e0e0e0;
        }
        
        .main-content {
            padding: 30px;
            display: grid;
            grid-template-rows: auto auto 1fr;
            gap: 25px;
        }
        
        .dashboard {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 25px;
        }
        
        .stat-card {
            background: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
            border-left: 4px solid var(--primary);
            text-align: center;
        }
        
        .stat-value {
            font-size: 2rem;
            font-weight: bold;
            color: var(--primary);
            margin-bottom: 5px;
        }
        
        .stat-label {
            color: var(--gray);
            font-size: 0.9rem;
        }
        
        .workflow-section {
            background: white;
            border-radius: 12px;
            padding: 25px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
            margin-bottom: 25px;
        }
        
        h2 {
            color: var(--primary);
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 2px solid #eaeaea;
            font-size: 1.5rem;
        }
        
        h3 {
            color: var(--secondary);
            margin-bottom: 15px;
            font-size: 1.2rem;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: var(--dark);
        }
        
        input, select, textarea, button {
            width: 100%;
            padding: 12px 15px;
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            font-size: 16px;
            transition: all 0.3s ease;
        }
        
        input:focus, select:focus, textarea:focus {
            outline: none;
            border-color: var(--primary);
            box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.1);
        }
        
        button {
            background: linear-gradient(135deg, var(--primary) 0%, var(--secondary) 100%);
            color: white;
            border: none;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.3s ease;
        }
        
        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 7px 14px rgba(67, 97, 238, 0.3);
        }
        
        button:disabled {
            background: #b0b0b0;
            cursor: not-allowed;
            transform: none;
            box-shadow: none;
        }
        
        .file-upload {
            border: 3px dashed var(--primary);
            padding: 30px;
            text-align: center;
            border-radius: 10px;
            margin-bottom: 20px;
            background: rgba(67, 97, 238, 0.05);
            transition: all 0.3s ease;
        }
        
        .file-upload:hover {
            background: rgba(67, 97, 238, 0.1);
        }
        
        .index-card {
            background: white;
            border: 2px solid #e0e0e0;
            border-radius: 10px;
            padding: 18px;
            margin-bottom: 12px;
            cursor: pointer;
            transition: all 0.3s ease;
        }
        
        .index-card:hover {
            border-color: var(--primary);
            box-shadow: 0 5px 15px rgba(67, 97, 238, 0.1);
            transform: translateY(-2px);
        }
        
        .index-card.selected {
            border-color: var(--primary);
            background: rgba(67, 97, 238, 0.05);
        }
        
        .index-name {
            font-weight: bold;
            margin-bottom: 8px;
            color: var(--dark);
        }
        
        .index-desc {
            font-size: 0.85rem;
            color: var(--gray);
            line-height: 1.4;
        }
        
        .system-info {
            background: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
            margin-top: 25px;
        }
        
        .status {
            display: inline-block;
            padding: 5px 12px;
            border-radius: 20px;
            font-size: 0.8rem;
            font-weight: bold;
            margin-bottom: 10px;
        }
        
        .status-success {
            background: #4ade80;
            color: white;
        }
        
        .status-warning {
            background: #f59e0b;
            color: white;
        }
        
        .status-error {
            background: #ef4444;
            color: white;
        }
        
        .status-info {
            background: var(--info);
            color: white;
        }
        
        .result-item {
            background: white;
            border: 1px solid #e0e0e0;
            border-radius: 10px;
            padding: 20px;
            margin-bottom: 20px;
            box-shadow: 0 3px 10px rgba(0, 0, 0, 0.05);
            transition: all 0.3s ease;
        }
        
        .result-item:hover {
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
        }
        
        .result-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }
        
        .result-rank {
            background: var(--primary);
            color: white;
            border-radius: 50%;
            width: 35px;
            height: 35px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
            font-size: 1.1rem;
        }
        
        .result-score {
            color: var(--success);
            font-weight: bold;
            font-size: 1.1rem;
        }
        
        .result-content {
            line-height: 1.6;
            color: var(--dark);
        }
        
        .timing-info {
            background: var(--light);
            border-radius: 8px;
            padding: 15px;
            margin-bottom: 20px;
        }
        
        .timing-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
            gap: 15px;
        }
        
        .timing-item {
            text-align: center;
            padding: 10px;
        }
        
        .timing-value {
            font-size: 1.5rem;
            font-weight: bold;
            color: var(--primary);
        }
        
        .timing-label {
            font-size: 0.9rem;
            color: var(--gray);
        }
        
        .performance-chart {
            background: white;
            border-radius: 10px;
            padding: 20px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
            margin-top: 25px;
        }
        
        .chart-container {
            height: 300px;
            position: relative;
        }
        
        .hidden {
            display: none;
        }
        
        .loading {
            text-align: center;
            padding: 30px;
        }
        
        .spinner {
            border: 4px solid #f3f3f3;
            border-top: 4px solid var(--primary);
            border-radius: 50%;
            width: 50px;
            height: 50px;
            animation: spin 1s linear infinite;
            margin: 0 auto 20px;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .tab-container {
            margin-top: 20px;
        }
        
        .tabs {
            display: flex;
            border-bottom: 2px solid #e0e0e0;
            margin-bottom: 20px;
        }
        
        .tab {
            padding: 12px 25px;
            cursor: pointer;
            border-bottom: 3px solid transparent;
            transition: all 0.3s ease;
        }
        
        .tab.active {
            border-bottom: 3px solid var(--primary);
            color: var(--primary);
            font-weight: bold;
        }
        
        .tab-content {
            display: none;
        }
        
        .tab-content.active {
            display: block;
        }
        
        .comparison-table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 15px;
        }
        
        .comparison-table th,
        .comparison-table td {
            padding: 12px 15px;
            text-align: left;
            border-bottom: 1px solid #e0e0e0;
        }
        
        .comparison-table th {
            background: var(--light);
            font-weight: 600;
        }
        
        .comparison-table tr:hover {
            background: rgba(67, 97, 238, 0.05);
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>🚀 Faiss 向量搜索引擎</h1>
            <p class="subtitle">GPU/CPU 性能对比与可视化分析平台</p>
        </header>
        
        <div class="content">
            <div class="sidebar">
                <h2>📊 系统状态</h2>
                <div id="systemStatus" class="system-info">
                    <p>正在检测系统信息...</p>
                </div>
                
                <h2 style="margin-top: 25px;">🔍 索引类型</h2>
                <div id="indexSelection">
                    <!-- 索引选项将通过JavaScript动态生成 -->
                </div>
                
                <div class="performance-chart">
                    <h2>📈 性能监控</h2>
                    <div id="performanceDashboard">
                        <p>执行搜索后查看性能数据...</p>
                    </div>
                </div>
            </div>
            
            <div class="main-content">
                <div class="dashboard" id="statsDashboard">
                    <div class="stat-card">
                        <div class="stat-value" id="totalSearches">0</div>
                        <div class="stat-label">总搜索次数</div>
                    </div>
                    <div class="stat-card">
                        <div class="stat-value" id="avgSearchTime">0ms</div>
                        <div class="stat-label">平均搜索时间</div>
                    </div>
                    <div class="stat-card">
                        <div class="stat-value" id="bestSearchTime">0ms</div>
                        <div class="stat-label">最佳搜索时间</div>
                    </div>
                    <div class="stat-card">
                        <div class="stat-value" id="gpuUsage">0%</div>
                        <div class="stat-label">GPU使用率</div>
                    </div>
                </div>
                
                <div class="workflow-section">
                    <h2>📁 1. 上传文档</h2>
                    <div class="form-group">
                        <div class="file-upload" id="dropZone">
                            <p>📎 拖放文件到这里或点击上传（支持多选）</p>
                            <p style="font-size: 0.9rem; margin-top: 10px; color: var(--gray);">支持格式: TXT, MD</p>
                            <input type="file" id="fileInput" accept=".txt,.md" multiple style="display: none;">
                            <button type="button" id="uploadButton" style="margin-top: 15px; width: auto; padding: 10px 25px;">选择文件</button>
                        </div>
                        <div id="fileList" style="margin-top: 15px;"></div>
                    </div>
                    <div id="uploadResult"></div>
                </div>
                
                <div class="workflow-section">
                    <h2>⚙️ 2. 构建索引</h2>
                    <div class="form-group">
                        <label for="deviceSelect">运行设备:</label>
                        <select id="deviceSelect">
                            <option value="cpu">💻 CPU</option>
                            <option value="gpu">🎮 GPU (如果可用)</option>
                        </select>
                    </div>
                    <button id="buildIndexButton" disabled>🚀 构建向量索引</button>
                    <div id="buildResult" style="margin-top: 15px;"></div>
                </div>
                
                <div class="workflow-section">
                    <h2>🔎 3. 搜索查询</h2>
                    <div class="form-group">
                        <label for="queryInput">输入查询:</label>
                        <textarea id="queryInput" rows="3" placeholder="输入您要搜索的内容..."></textarea>
                    </div>
                    <div class="form-group">
                        <label for="topKInput">返回结果数量:</label>
                        <input type="number" id="topKInput" value="5" min="1" max="20">
                    </div>
                    <button id="searchButton" disabled>🔍 执行搜索</button>
                    
                    <div id="timingResults" class="timing-info" style="display: none;">
                        <h3>⏱️ 性能指标</h3>
                        <div class="timing-grid">
                            <div class="timing-item">
                                <div class="timing-value" id="embedTime">0ms</div>
                                <div class="timing-label">向量化时间</div>
                            </div>
                            <div class="timing-item">
                                <div class="timing-value" id="searchTime">0ms</div>
                                <div class="timing-label">搜索时间</div>
                            </div>
                            <div class="timing-item">
                                <div class="timing-value" id="totalTime">0ms</div>
                                <div class="timing-label">总时间</div>
                            </div>
                            <div class="timing-item">
                                <div class="timing-value" id="speedup">1.0x</div>
                                <div class="timing-label">性能加速比</div>
                            </div>
                        </div>
                    </div>
                    
                    <div id="searchResults" style="margin-top: 20px;"></div>
                </div>
                
                <div class="tab-container">
                    <div class="tabs">
                        <div class="tab active" data-tab="performance">📊 性能分析</div>
                        <div class="tab" data-tab="comparison">⚡ 对比数据</div>
                        <div class="tab" data-tab="history">📋 搜索历史</div>
                    </div>
                    
                    <div class="tab-content active" id="performance-tab">
                        <div class="performance-chart">
                            <h3>搜索时间对比</h3>
                            <div class="chart-container">
                                <canvas id="performanceChart"></canvas>
                            </div>
                        </div>
                    </div>
                    
                    <div class="tab-content" id="comparison-tab">
                        <div class="performance-chart">
                            <h3>索引类型性能对比</h3>
                            <table class="comparison-table">
                                <thead>
                                    <tr>
                                        <th>索引类型</th>
                                        <th>设备</th>
                                        <th>平均搜索时间</th>
                                        <th>最佳搜索时间</th>
                                        <th>搜索次数</th>
                                    </tr>
                                </thead>
                                <tbody id="comparisonTableBody">
                                    <!-- 对比数据将通过JavaScript动态生成 -->
                                </tbody>
                            </table>
                        </div>
                    </div>
                    
                    <div class="tab-content" id="history-tab">
                        <div class="performance-chart">
                            <h3>最近搜索记录</h3>
                            <table class="comparison-table">
                                <thead>
                                    <tr>
                                        <th>时间</th>
                                        <th>索引类型</th>
                                        <th>设备</th>
                                        <th>向量化时间</th>
                                        <th>搜索时间</th>
                                        <th>总时间</th>
                                    </tr>
                                </thead>
                                <tbody id="historyTableBody">
                                    <!-- 历史数据将通过JavaScript动态生成 -->
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 全局变量
        let currentFileId = null;
        let currentIndexType = 'FlatL2';
        let performanceChart = null;
        let baselinePerformance = {};
        
        // 初始化索引选择
        function initIndexSelection() {
            const indexes = {
                'FlatL2': {name: '精确搜索 (FlatL2)', description: '暴力搜索，100%准确率，适合小数据集'},
                'IVFFlat': {name: '倒排索引 (IVFFlat)', description: '平衡精度和速度，适合中等数据集'},
                'IVFPQ': {name: '乘积量化 (IVFPQ)', description: '内存优化，适合大规模数据集'}
            };
            
            let htmlContent = '';
            for (const [key, value] of Object.entries(indexes)) {
                htmlContent += `
                    <div class="index-card ${key === 'FlatL2' ? 'selected' : ''}" data-index="${key}">
                        <div class="index-name">${value.name}</div>
                        <div class="index-desc">${value.description}</div>
                    </div>
                `;
            }
            
            document.getElementById('indexSelection').innerHTML = htmlContent;
            
            // 绑定索引选择事件
            document.querySelectorAll('.index-card').forEach(card => {
                card.addEventListener('click', function() {
                    document.querySelectorAll('.index-card').forEach(c => c.classList.remove('selected'));
                    this.classList.add('selected');
                    currentIndexType = this.getAttribute('data-index');
                });
            });
        }
        
        // DOM 加载完成后初始化
        document.addEventListener('DOMContentLoaded', function() {
            // 初始化系统信息
            loadSystemInfo();
            
            // 初始化索引选择
            initIndexSelection();
            
            // 初始化标签页
            initTabs();
            
            // 绑定事件
            document.getElementById('uploadButton').addEventListener('click', function() {
                document.getElementById('fileInput').click();
            });
            // 添加上传按钮
            const uploadSubmitButton = document.createElement('button');
            uploadSubmitButton.textContent = '上传文件';
            uploadSubmitButton.type = 'button';
            uploadSubmitButton.id = 'uploadSubmitButton';
            uploadSubmitButton.style.marginTop = '15px';
            document.querySelector('.file-upload').appendChild(uploadSubmitButton);

            // 绑定上传事件
            document.getElementById('uploadSubmitButton').addEventListener('click', uploadFiles);
            document.getElementById('fileInput').addEventListener('change', handleFileUpload);
            
            document.getElementById('buildIndexButton').addEventListener('click', buildIndex);
            
            document.getElementById('searchButton').addEventListener('click', performSearch);
            
            // 拖放功能
            const dropZone = document.getElementById('dropZone');
            dropZone.addEventListener('dragover', function(e) {
                e.preventDefault();
                dropZone.style.backgroundColor = 'rgba(67, 97, 238, 0.1)';
            });
            
            dropZone.addEventListener('dragleave', function(e) {
                e.preventDefault();
                dropZone.style.backgroundColor = '';
            });
            
            dropZone.addEventListener('drop', function(e) {
                e.preventDefault();
                dropZone.style.backgroundColor = '';

                if (e.dataTransfer.files.length) {
                    handleFiles(e.dataTransfer.files);
                }
            });
            
            // 加载性能数据
            loadPerformanceStats();
        });
        
        // 初始化标签页
        function initTabs() {
            document.querySelectorAll('.tab').forEach(tab => {
                tab.addEventListener('click', function() {
                    // 移除所有active类
                    document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
                    document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
                    
                    // 添加active类到当前标签
                    this.classList.add('active');
                    const tabId = this.getAttribute('data-tab');
                    document.getElementById(`${tabId}-tab`).classList.add('active');
                });
            });
        }
        
        // 加载系统信息
        function loadSystemInfo() {
            fetch('/system_info')
                .then(response => {
                    if (!response.ok) {
                        throw new Error('网络响应不正常');
                    }
                    return response.json();
                })
                .then(data => {
                    const systemStatus = document.getElementById('systemStatus');
                    
                    let html = `<p><strong>Faiss 版本:</strong> ${data.faiss_version}</p>`;
                    html += `<p><strong>当前设备:</strong> ${data.current_device.toUpperCase()}</p>`;
                    html += `<p><strong>搜索记录:</strong> ${data.performance_records} 次</p>`;
                    
                    if (data.gpu_available) {
                        html += `<p><span class="status status-success">🎮 GPU 可用</span></p>`;
                        html += `<p><strong>GPU 设备:</strong> ${data.gpu_info.device_name}</p>`;
                        html += `<p><strong>显存:</strong> ${data.gpu_info.memory.toFixed(1)} GB</p>`;
                    } else {
                        html += `<p><span class="status status-warning">💻 GPU 不可用</span></p>`;
                    }
                    html += `<p><strong>处理文件:</strong> ${data.files_processed || 0} 个</p>`;
                    systemStatus.innerHTML = html;
                })
                .catch(error => {
                    console.error('获取系统信息失败:', error);
                    document.getElementById('systemStatus').innerHTML = 
                        '<p class="status status-error">无法获取系统信息</p>';
                });
        }
        let selectedFiles = [];
        
        // 处理文件上传
        function handleFileUpload(e) {
            handleFiles(e.target.files);
        }
        
        function handleFiles(files) {
            if (files.length === 0) return;

            selectedFiles = Array.from(files);
            updateFileList();
        }

        function updateFileList() {
            const fileList = document.getElementById('fileList');

            if (selectedFiles.length === 0) {
                fileList.innerHTML = '<p style="color: var(--gray);">未选择文件</p>';
                return;
            }

            let html = '<div style="border: 1px solid #e0e0e0; border-radius: 8px; padding: 15px; background: var(--light);">';
            html += '<p style="font-weight: bold; margin-bottom: 10px;">已选择文件:</p>';

            selectedFiles.forEach((file, index) => {
                html += `
                    <div style="display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid #e0e0e0;">
                        <span>${file.name}</span>
                        <span style="color: var(--gray); font-size: 0.9rem;">${(file.size / 1024).toFixed(2)} KB</span>
                    </div>
                `;
            });

            html += `<p style="margin-top: 10px; font-weight: bold;">总计: ${selectedFiles.length} 个文件</p>`;
            html += '</div>';

            fileList.innerHTML = html;
        }
        // 修改上传函数
        function uploadFiles() {
            if (selectedFiles.length === 0) {
                alert('请先选择文件');
                return;
            }

            const formData = new FormData();
            selectedFiles.forEach(file => {
                formData.append('files', file);
            });

            // 显示上传状态
            const uploadResult = document.getElementById('uploadResult');
            uploadResult.innerHTML = '<div class="loading"><div class="spinner"></div><p>正在上传和处理文件...</p></div>';

            fetch('/upload', {
                method: 'POST',
                body: formData
            })
            .then(response => {
                if (!response.ok) {
                    return response.text().then(text => {
                        throw new Error(text || '上传失败');
                    });
                }
                return response.json();
            })
            .then(data => {
                if (data.success) {
                    currentFileId = data.file_id;

                    let filesHtml = '';
                    data.files.forEach(file => {
                        filesHtml += `<p>📄 ${file.filename} (${file.chunk_count} 个片段)</p>`;
                    });

                    uploadResult.innerHTML = `
                        <div class="status status-success">
                            ✅ ${data.files.length} 个文件上传成功！
                        </div>
                        ${filesHtml}
                        <p>📊 总片段数: ${data.total_chunks}</p>
                        <p>🔢 向量维度: ${data.vector_dim}</p>
                    `;

                    // 启用构建索引按钮
                    document.getElementById('buildIndexButton').disabled = false;

                    // 清空文件列表
                    selectedFiles = [];
                    updateFileList();
                } else {
                    uploadResult.innerHTML = `
                        <div class="status status-error">
                            ❌ 上传失败: ${data.error}
                        </div>
                    `;
                }
            })
            .catch(error => {
                console.error('上传失败:', error);
                let errorMsg = error.message;
                try {
                    const errorObj = JSON.parse(error.message);
                    errorMsg = errorObj.error || error.message;
                } catch (e) {
                    // 如果不是JSON，直接使用原错误消息
                }

                uploadResult.innerHTML = `
                    <div class="status status-error">
                        ❌ 上传失败: ${errorMsg}
                    </div>
                `;
            });
        }

        // 修改搜索结果显示
        function displaySearchResults(data) {
            let resultsHtml = `
                <div class="status status-success">
                    ✅ 搜索完成 (索引: ${data.index_type}, 设备: ${data.device.toUpperCase()})
                </div>
            `;

            if (data.results && data.results.length > 0) {
                data.results.forEach(result => {
                    resultsHtml += `
                        <div class="result-item">
                            <div class="result-header">
                                <div class="result-rank">${result.rank}</div>
                                <div class="result-score">相似度: ${(result.score * 100).toFixed(2)}%</div>
                            </div>
                            <div style="margin-bottom: 10px; color: var(--gray); font-size: 0.9rem;">
                                来源: ${result.filename}
                            </div>
                            <div class="result-content">${result.content}</div>
                        </div>
                    `;
                });
            } else {
                resultsHtml += '<p>未找到相关结果</p>';
            }

            return resultsHtml;
        }
        // 构建索引
        function buildIndex() {
            if (!currentFileId) {
                alert('请先上传文件');
                return;
            }
            
            const device = document.getElementById('deviceSelect').value;
            const buildResult = document.getElementById('buildResult');
            
            buildResult.innerHTML = '<div class="loading"><div class="spinner"></div><p>正在构建索引...</p></div>';
            
            fetch('/build_index', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    file_id: currentFileId,
                    index_type: currentIndexType,
                    device: device
                })
            })
            .then(response => {
                if (!response.ok) {
                    return response.text().then(text => {
                        throw new Error(text || '构建索引失败');
                    });
                }
                return response.json();
            })
            .then(data => {
                if (data.success) {
                    buildResult.innerHTML = `
                        <div class="status status-success">
                            ✅ 索引构建成功！
                        </div>
                        <p>🔧 索引类型: ${data.index_type}</p>
                        <p>💻 运行设备: ${data.device.toUpperCase()}</p>
                        <p>📊 向量数量: ${data.vector_count}</p>
                        <p>⏱️ 构建时间: ${(data.build_time * 1000).toFixed(2)} ms</p>
                    `;
                    
                    // 启用搜索按钮
                    document.getElementById('searchButton').disabled = false;
                    
                    // 更新系统信息
                    loadSystemInfo();
                } else {
                    buildResult.innerHTML = `
                        <div class="status status-error">
                            ❌ 索引构建失败: ${data.error}
                        </div>
                    `;
                }
            })
            .catch(error => {
                console.error('构建索引失败:', error);
                // 尝试解析错误消息
                let errorMsg = error.message;
                try {
                    const errorObj = JSON.parse(error.message);
                    errorMsg = errorObj.error || error.message;
                } catch (e) {
                    // 如果不是JSON，直接使用原错误消息
                }
                
                buildResult.innerHTML = `
                    <div class="status status-error">
                        ❌ 构建索引失败: ${errorMsg}
                    </div>
                `;
            });
        }
        
        // 执行搜索
        function performSearch() {
            if (!currentFileId) {
                alert('请先上传文件并构建索引');
                return;
            }
            
            const query = document.getElementById('queryInput').value.trim();
            const topK = document.getElementById('topKInput').value;
            const searchResults = document.getElementById('searchResults');
            
            if (!query) {
                alert('请输入查询内容');
                return;
            }
            
            searchResults.innerHTML = '<div class="loading"><div class="spinner"></div><p>正在搜索...</p></div>';
            
            fetch('/search', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    file_id: currentFileId,
                    query: query,
                    top_k: parseInt(topK)
                })
            })
            .then(response => {
                if (!response.ok) {
                    return response.text().then(text => {
                        throw new Error(text || '搜索失败');
                    });
                }
                return response.json();
            })
            .then(data => {
                if (data.success) {
                    // 显示时间信息
                    document.getElementById('timingResults').style.display = 'block';
                    document.getElementById('embedTime').textContent = `${(data.timing.embedding * 1000).toFixed(2)} ms`;
                    document.getElementById('searchTime').textContent = `${(data.timing.search * 1000).toFixed(2)} ms`;
                    document.getElementById('totalTime').textContent = `${(data.timing.total * 1000).toFixed(2)} ms`;
                    
                    // 计算加速比
                    const key = `${data.index_type}_${data.device}`;
                    if (!baselinePerformance[key]) {
                        baselinePerformance[key] = data.timing.search;
                    }
                    const speedup = baselinePerformance[key] / data.timing.search;
                    document.getElementById('speedup').textContent = `${speedup.toFixed(2)}x`;
                    
                    let resultsHtml = `
                        <div class="status status-success">
                            ✅ 搜索完成 (索引: ${data.index_type}, 设备: ${data.device.toUpperCase()})
                        </div>
                    `;
                    
                    if (data.results && data.results.length > 0) {
                        data.results.forEach(result => {
                            resultsHtml += `
                                <div class="result-item">
                                    <div class="result-header">
                                        <div class="result-rank">${result.rank}</div>
                                        <div class="result-score">相似度: ${(result.score * 100).toFixed(2)}%</div>
                                    </div>
                                    <div class="result-content">${result.content}</div>
                                </div>
                            `;
                        });
                    } else {
                        resultsHtml += '<p>未找到相关结果</p>';
                    }
                    
                    searchResults.innerHTML = resultsHtml;
                    
                    // 更新性能数据
                    loadPerformanceStats();
                    
                } else {
                    searchResults.innerHTML = `
                        <div class="status status-error">
                            ❌ 搜索失败: ${data.error}
                        </div>
                    `;
                }
            })
            .catch(error => {
                console.error('搜索失败:', error);
                // 尝试解析错误消息
                let errorMsg = error.message;
                try {
                    const errorObj = JSON.parse(error.message);
                    errorMsg = errorObj.error || error.message;
                } catch (e) {
                    // 如果不是JSON，直接使用原错误消息
                }
                
                searchResults.innerHTML = `
                    <div class="status status-error">
                        ❌ 搜索失败: ${errorMsg}
                    </div>
                `;
            });
        }
        
        // 加载性能统计
        function loadPerformanceStats() {
            fetch('/performance_stats')
                .then(response => response.json())
                .then(data => {
                    if (data.stats) {
                        updateDashboard(data);
                        updateComparisonTable(data.stats);
                        updateHistoryTable(data.recent);
                        updatePerformanceChart(data.stats);
                    }
                })
                .catch(error => {
                    console.error('获取性能统计失败:', error);
                });
        }
        
        // 更新仪表板
        function updateDashboard(data) {
            let totalSearches = 0;
            let totalSearchTime = 0;
            let bestSearchTime = Infinity;
            let gpuSearches = 0;
            
            data.stats.forEach(stat => {
                totalSearches += stat.count;
                totalSearchTime += stat.total_search_time;
                if (stat.best_search_time < bestSearchTime) {
                    bestSearchTime = stat.best_search_time;
                }
                if (stat.device === 'gpu') {
                    gpuSearches += stat.count;
                }
            });
            
            const avgSearchTime = totalSearches > 0 ? (totalSearchTime / totalSearches * 1000).toFixed(2) : '0';
            const gpuUsage = totalSearches > 0 ? ((gpuSearches / totalSearches) * 100).toFixed(1) : '0';
            
            document.getElementById('totalSearches').textContent = totalSearches;
            document.getElementById('avgSearchTime').textContent = `${avgSearchTime} ms`;
            document.getElementById('bestSearchTime').textContent = `${(bestSearchTime * 1000).toFixed(2)} ms`;
            document.getElementById('gpuUsage').textContent = `${gpuUsage}%`;
        }
        
        // 更新对比表格
        function updateComparisonTable(stats) {
            const tableBody = document.getElementById('comparisonTableBody');
            let html = '';
            
            stats.forEach(stat => {
                html += `
                    <tr>
                        <td>${stat.index_type}</td>
                        <td>${stat.device.toUpperCase()}</td>
                        <td>${(stat.avg_search_time * 1000).toFixed(2)} ms</td>
                        <td>${(stat.best_search_time * 1000).toFixed(2)} ms</td>
                        <td>${stat.count}</td>
                    </tr>
                `;
            });
            
            tableBody.innerHTML = html;
        }
        
        // 更新历史表格
        function updateHistoryTable(history) {
            const tableBody = document.getElementById('historyTableBody');
            let html = '';
            
            history.reverse().forEach(record => {
                const date = new Date(record.timestamp * 1000);
                const timeStr = date.toLocaleTimeString();
                
                html += `
                    <tr>
                        <td>${timeStr}</td>
                        <td>${record.index_type}</td>
                        <td>${record.device.toUpperCase()}</td>
                        <td>${(record.embed_time * 1000).toFixed(2)} ms</td>
                        <td>${(record.search_time * 1000).toFixed(2)} ms</td>
                        <td>${(record.total_time * 1000).toFixed(2)} ms</td>
                    </tr>
                `;
            });
            
            tableBody.innerHTML = html;
        }
        
        // 更新性能图表
        function updatePerformanceChart(stats) {
            const ctx = document.getElementById('performanceChart').getContext('2d');
            
            // 销毁旧图表
            if (performanceChart) {
                performanceChart.destroy();
            }
            
            const labels = stats.map(stat => `${stat.index_type} (${stat.device})`);
            const avgSearchTimes = stats.map(stat => stat.avg_search_time * 1000);
            const bestSearchTimes = stats.map(stat => stat.best_search_time * 1000);
            
            performanceChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: labels,
                    datasets: [
                        {
                            label: '平均搜索时间 (ms)',
                            data: avgSearchTimes,
                            backgroundColor: 'rgba(67, 97, 238, 0.7)',
                            borderColor: 'rgba(67, 97, 238, 1)',
                            borderWidth: 1
                        },
                        {
                            label: '最佳搜索时间 (ms)',
                            data: bestSearchTimes,
                            backgroundColor: 'rgba(76, 201, 240, 0.7)',
                            borderColor: 'rgba(76, 201, 240, 1)',
                            borderWidth: 1
                        }
                    ]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        y: {
                            beginAtZero: true,
                            title: {
                                display: true,
                                text: '时间 (毫秒)'
                            }
                        }
                    },
                    plugins: {
                        title: {
                            display: true,
                            text: '不同索引类型的搜索性能对比'
                        }
                    }
                }
            });
        }
    </script>
</body>
</html>